﻿
using Microsoft.Win32;
using SUNRPA.CONTROLS.IMPL.domain;
using SUNRPA.CONTROLS.IMPL.domain.constant;
using SUNRPA.CONTROLS.IMPL.domain.flowRunningVar;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Policy;
using System.Windows.Automation;

namespace SUNRPA.CONTROLS.IMPL.util {
    public class ChromeUtil:BrowserUtil {
        public override void ActiveBrowser() {
            Process[] chromes = Process.GetProcessesByName("chrome");
            /*Process googleProcess = null;
            foreach(Process p in chromes){ 
                if("Google Chrome-".Equals(p.StartInfo.FileName)){
                    googleProcess = p;
                    break;
                }
            }*/
            if(chromes != null || chromes.Length > 0) {
                foreach(Process p in chromes) {
                    if(!p.MainWindowHandle.Equals(new IntPtr(0))) { 
                        User32Utils.SetForegroundWindow(p.MainWindowHandle);
                        User32Utils.SetFocus(p.MainWindowHandle);
                        break;
                    }
                }
            }
        }

        public override void DealDownLoadDialog(bool isDownload, string parentPath, string fileName, int expireTime) {
            IntPtr downloadDialogHandle = User32Utils.FindWindow(null, "另存为");
            for(int i = 0; i < expireTime; i++){
                Thread.Sleep(1000);
                downloadDialogHandle = User32Utils.FindWindow(null, "另存为");
                if(downloadDialogHandle.ToInt32() != 0) { 
                    break;
                }
            }
            if(downloadDialogHandle.ToInt32() == 0) { 
                throw new RpaRuntimeException("没有找到下载对话框");
            }
            AutomationElement ae = AutomationElement.FromHandle(downloadDialogHandle);
            if(ae == null) { 
                throw new RpaRuntimeException("没有找到下载对话框");
            }
            Condition cancelCondition = new AndCondition(
                new PropertyCondition(AutomationElement.NameProperty, "取消"),
                new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button)
            );
            Condition saveConditon = new AndCondition(
                new PropertyCondition(AutomationElement.NameProperty, "保存(S)"),
                new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button)
            );
            if(isDownload){
                //保存
                AutomationElement saveAe = ae.FindFirst(TreeScope.Descendants, saveConditon);
                InvokePattern saveButtonPattern = saveAe.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;

                if(!string.IsNullOrEmpty(parentPath)){
                    Condition progressBarCon = new AndCondition(
                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ProgressBar),
                        new PropertyCondition(AutomationElement.ClassNameProperty, "msctls_progress32")
                    );
                    
                    Condition toolBarCon = new AndCondition(
                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ToolBar),
                        new PropertyCondition(AutomationElement.ClassNameProperty, "ToolbarWindow32"),
                        new PropertyCondition(AutomationElement.LocalizedControlTypeProperty, "工具栏")
                    );

                    AutomationElement toolBarAe = ae.FindFirst(TreeScope.Descendants, progressBarCon).FindFirst(TreeScope.Descendants, toolBarCon);
                    User32Utils.SetForegroundWindow(downloadDialogHandle);
                    System.Windows.Point point = toolBarAe.GetClickablePoint();
                    User32Utils.SetCursorPos((int)point.X, (int)point.Y-10);
                    User32Utils.LeftClick();


                    Condition editAddrCon = new AndCondition(
                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit),
                        new PropertyCondition(AutomationElement.NameProperty, "地址")
                    );
                    AutomationElement editAddrAe = ae.FindFirst(TreeScope.Descendants, editAddrCon);
                    ValuePattern valuePattern = editAddrAe.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                    valuePattern.SetValue(parentPath);
                    SendKeys.SendWait("{ENTER}");
                }
                Thread.Sleep(1000);
                Condition fileNameConditon = new AndCondition(
                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit),
                    new PropertyCondition(AutomationElement.NameProperty, "文件名:")
                );
                AutomationElement fileNameAe = ae.FindFirst(TreeScope.Descendants, fileNameConditon);
                if(!string.IsNullOrEmpty(fileName)){
                    ValuePattern valuePattern = fileNameAe.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                    valuePattern.SetValue(fileName);
                }
                saveButtonPattern.Invoke();
                Thread.Sleep(1000);
            } else{ 
                //取消
                AutomationElement cancleAe = ae.FindFirst(TreeScope.Children, cancelCondition);
                InvokePattern buttonPattern = cancleAe.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
                buttonPattern.Invoke();
            }
        }

        public override bool IsDownloadExpire(int downloadId, int expireTime) {
            bool finished = false;
            //通过downloadid查询下载进度
            NamePipeRequest request = new NamePipeRequest();
            request.method = DefaultContents.ISDOWNLOAD_FINISHED;
            request.requestData = new Dictionary<string, object>() { { "id", downloadId } };
            for(int i = 0; i < expireTime; i++) { 
                using(NamedPipeClientUtil client = new NamedPipeClientUtil("localhost"
                    , DefaultContents.NAMED_PIPE_SERVER, System.IO.Pipes.PipeDirection.InOut)) { 
                    BridgeResponse resp = client.SendRequest(request);
                    if(resp.code.Equals(CommunicationCode.OK) && bool.Parse(resp.result.ToString())) {
                        finished = true;
                        break;
                    }
                }
                Thread.Sleep(1000);
            }
            if(!finished) { 
                return true;
            } else { 
                return false;
            }
        }

        public override object OpenUrl(string url, int expireTime, string? appPath) {
            //1、检查google浏览器是否已经启动
            //2、未启动google则根据apppath或者默认路径启动chrome
            //3、与浏览器插件联系、新建tab打开url
            //4、收到插件返回的web信息（tabid之类）
            Process[] chromes = Process.GetProcessesByName("chrome");
            /*Process googleProcess = null;
            foreach(Process p in chromes){ 
                if("Google Chrome-".Equals(p.StartInfo.FileName)){
                    googleProcess = p;
                    break;
                }
            }*/
            if(chromes == null || chromes.Length <= 0) {
                OpenChrome(appPath, "--force-renderer-accessibility");
            }
            NamePipeRequest req = new NamePipeRequest();
            req.method = DefaultContents.OPEN_WEBPAGE;
            req.requestData = new Dictionary<string, object>() { { "url", url } };
            BridgeResponse resp = NamedPipeClientUtil.SendRequestV1(req);
            if(resp.code.Equals(CommunicationCode.OK)) {
                int tabId = int.Parse(resp.result.ToString());
                return WebPage.CreateChromeWebPage(tabId);
            }
            return null;
        }

        private void OpenChrome(string? appPath, string param){
            try {
                if(string.IsNullOrEmpty(appPath)) {
                    appPath = GetChromePath();
                }
                var result = default(Process);
                if(!string.IsNullOrWhiteSpace(appPath) && File.Exists(appPath)){
                    result = Process.Start(appPath, param);
                }
                if(result == null) {
                    result = Process.Start("chrome.exe", param);
                }
                if(result == null) { 
                    throw new RpaRuntimeException("无法找到Chrome浏览器");
                }
            } catch(Exception e){
                throw new RpaRuntimeException($"打开google浏览器出错：{e.StackTrace}");
            }
        }


        public static string GetChromePath() {
            string chormePath = string.Empty;
            string chromeAppKey = @"\Software\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe";
            chormePath = (Registry.GetValue("HKEY_LOCAL_MACHINE" + chromeAppKey, "", null) ?? Registry.GetValue("HKEY_CURRENT_USER" + chromeAppKey, "", null))?.ToString();
            if(!string.IsNullOrWhiteSpace(chormePath) && File.Exists(chormePath))
                return chormePath;
            chormePath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\Google\Chrome\Application\chrome.exe";
            //win10默认安装路径
            if(!string.IsNullOrWhiteSpace(chormePath) && File.Exists(chormePath))
                return chormePath;
            string executeName = "chrome.exe";
            chormePath = SystemUtil.GetExecutePath(executeName);
            if(!string.IsNullOrWhiteSpace(chormePath) && File.Exists(chormePath))
                return chormePath;
            // 64位注册表路径
            var openKey_64 = @"SOFTWARE\Wow6432Node\Google\Chrome";
            RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(openKey_64);
            chormePath = registryKey?.GetValue(string.Empty)?.ToString();
            if(!string.IsNullOrWhiteSpace(chormePath) && File.Exists(chormePath))
                return chormePath;

            var openKey_32 = @"SOFTWARE\Google\Chrome";
            registryKey = Registry.LocalMachine.OpenSubKey(openKey_32);
            chormePath = registryKey?.GetValue(string.Empty)?.ToString();
            if(!string.IsNullOrWhiteSpace(chormePath) && File.Exists(chormePath))
                return chormePath;
            return chormePath;
        }

        public override bool WaitWebEle(int waitType, bool canExpire, WebElement ele, object webPage, [Optional] int expireTime) {
            WebPage wp = (WebPage)webPage;
            bool finished = false;
            //通过downloadid查询下载进度
            NamePipeRequest request = new NamePipeRequest();
            if(waitType == 0) {
                 request.method = DefaultContents.WAIT_ELE_SHOWUP;
            } else { 
                 request.method = DefaultContents.WAIT_ELE_DISAPPER;
            }
            request.requestData = new Dictionary<string, object>() { { "tabId", wp.TabId}, { "ele", ele } };
            if(canExpire) {
                for(int i = 0; i < expireTime; i++) { 
                    using(NamedPipeClientUtil client = new NamedPipeClientUtil("localhost"
                        , DefaultContents.NAMED_PIPE_SERVER, System.IO.Pipes.PipeDirection.InOut)) { 
                        BridgeResponse resp = client.SendRequest(request);
                        if(resp.code.Equals(CommunicationCode.OK) && bool.Parse(resp.result.ToString())) {
                            finished = true;
                            break;
                        }
                    }
                    Thread.Sleep(1000);
                }
            } else {
                while(true) { 
                    using(NamedPipeClientUtil client = new NamedPipeClientUtil("localhost"
                        , DefaultContents.NAMED_PIPE_SERVER, System.IO.Pipes.PipeDirection.InOut)) { 
                        BridgeResponse resp = client.SendRequest(request);
                        if(resp.code.Equals(CommunicationCode.OK) && bool.Parse(resp.result.ToString())) {
                            finished = true;
                            break;
                        }
                    }
                    Thread.Sleep(1000);
                }
            }
            return finished;
        }

        public override object SearchLatestDownloadTask() {
            NamePipeRequest request = new NamePipeRequest();
            request.method = DefaultContents.SEARCH_LATEST_DOWNLOAD_ITEM;
            request.requestData = new Dictionary<string, object>() {
                { "orderBy", new string[]{ "-startTime"} },
                { "limit", 1}
            };
            BridgeResponse resp = NamedPipeClientUtil.SendRequestV1(request);
            if(!resp.code.Equals(CommunicationCode.OK)) {
                throw new RpaRuntimeException($"下载文件出错,没有找到下载任务:{resp.msg}");
            }
            return resp.result;
        }
    }
}
